#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <string.h>
#include <vector>
#include <string>
#include <thread>
#include <atomic>
#include <chrono>
#include <iomanip>
#include <map>
#include <mutex>

/**
 * 被动清理版 Epoll 服务器类
 * 
 * 修改策略：
 * 1. 不主动清理客户端连接
 * 2. 等待客户端主动断开连接
 * 3. 只在客户端真正断开时才清理
 * 4. 改进数据读取逻辑，避免误判断开
 */
class PassiveEpollServer {
private:
    int server_fd;                    // 服务器监听套接字
    int epoll_fd;                     // epoll 实例文件描述符
    int port;                         // 监听端口
    std::atomic<bool> running;        // 服务器运行状态
    std::atomic<int> client_count;    // 当前连接的客户端数量
    
    // 客户端连接管理
    std::map<int, std::string> client_info;  // 客户端信息映射
    std::mutex client_mutex;                  // 客户端信息互斥锁
    
    // 常量定义
    static const int MAX_EVENTS = 1024;    // epoll 最大事件数
    static const int BUFFER_SIZE = 1024;   // 缓冲区大小
    static const int MAX_CLIENTS = 10000;  // 最大客户端连接数

public:
    /**
     * 构造函数
     * @param port 监听端口号
     */
    PassiveEpollServer(int port) : port(port), server_fd(-1), epoll_fd(-1), 
                                  running(false), client_count(0) {
        std::cout << "=== 被动清理版 Epoll 服务器初始化 ===" << std::endl;
        std::cout << "监听端口: " << port << std::endl;
        std::cout << "最大事件数: " << MAX_EVENTS << std::endl;
        std::cout << "缓冲区大小: " << BUFFER_SIZE << " 字节" << std::endl;
        std::cout << "最大客户端数: " << MAX_CLIENTS << std::endl;
        std::cout << "清理策略: 被动清理（等待客户端主动断开）" << std::endl;
        std::cout << "=====================================" << std::endl;
    }

    /**
     * 析构函数 - 清理资源
     */
    ~PassiveEpollServer() {
        std::cout << "\n=== 服务器关闭，清理资源 ===" << std::endl;
        if (server_fd != -1) {
            close(server_fd);
            std::cout << "✓ 关闭服务器套接字" << std::endl;
        }
        if (epoll_fd != -1) {
            close(epoll_fd);
            std::cout << "✓ 关闭 epoll 实例" << std::endl;
        }
        std::cout << "✓ 资源清理完成" << std::endl;
    }

    /**
     * 设置文件描述符为非阻塞模式
     * @param fd 文件描述符
     * @return 成功返回 true，失败返回 false
     */
    bool setNonBlocking(int fd) {
        int flags = fcntl(fd, F_GETFL, 0);
        if (flags == -1) {
            std::cerr << "❌ 获取文件描述符标志失败: " << strerror(errno) << std::endl;
            return false;
        }
        
        if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
            std::cerr << "❌ 设置非阻塞模式失败: " << strerror(errno) << std::endl;
            return false;
        }
        
        return true;
    }

    /**
     * 将文件描述符添加到 epoll 监听列表
     * @param fd 文件描述符
     * @param events 监听的事件类型
     * @return 成功返回 true，失败返回 false
     */
    bool addToEpoll(int fd, uint32_t events) {
        struct epoll_event ev;
        ev.events = events;
        ev.data.fd = fd;
        
        if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev) == -1) {
            std::cerr << "❌ 添加文件描述符到 epoll 失败: " << strerror(errno) << std::endl;
            return false;
        }
        
        return true;
    }

    /**
     * 从 epoll 监听列表中移除文件描述符
     * @param fd 文件描述符
     * @return 成功返回 true，失败返回 false
     */
    bool removeFromEpoll(int fd) {
        if (epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, nullptr) == -1) {
            std::cerr << "❌ 从 epoll 移除文件描述符失败: " << strerror(errno) << std::endl;
            return false;
        }
        return true;
    }

    /**
     * 获取当前时间戳（用于日志）
     * @return 格式化的时间字符串
     */
    std::string getTimestamp() {
        auto now = std::chrono::system_clock::now();
        auto time_t = std::chrono::system_clock::to_time_t(now);
        auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
            now.time_since_epoch()) % 1000;
        
        std::stringstream ss;
        ss << std::put_time(std::localtime(&time_t), "%H:%M:%S");
        ss << '.' << std::setfill('0') << std::setw(3) << ms.count();
        return ss.str();
    }

    /**
     * 初始化服务器
     * @return 成功返回 true，失败返回 false
     */
    bool init() {
        std::cout << "\n=== 开始初始化服务器 ===" << std::endl;
        
        // 步骤 1: 创建 TCP 套接字
        std::cout << "1. 创建 TCP 套接字..." << std::endl;
        server_fd = socket(AF_INET, SOCK_STREAM, 0);
        if (server_fd == -1) {
            std::cerr << "❌ 创建套接字失败: " << strerror(errno) << std::endl;
            return false;
        }
        std::cout << "✓ 套接字创建成功，文件描述符: " << server_fd << std::endl;

        // 步骤 2: 设置套接字选项（地址重用）
        std::cout << "2. 设置套接字选项..." << std::endl;
        int opt = 1;
        if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
            std::cerr << "❌ 设置套接字选项失败: " << strerror(errno) << std::endl;
            return false;
        }
        std::cout << "✓ 地址重用选项设置成功" << std::endl;

        // 步骤 3: 设置非阻塞模式
        std::cout << "3. 设置非阻塞模式..." << std::endl;
        if (!setNonBlocking(server_fd)) {
            std::cerr << "❌ 设置非阻塞模式失败" << std::endl;
            return false;
        }
        std::cout << "✓ 非阻塞模式设置成功" << std::endl;

        // 步骤 4: 绑定地址和端口
        std::cout << "4. 绑定地址和端口..." << std::endl;
        struct sockaddr_in server_addr;
        memset(&server_addr, 0, sizeof(server_addr));
        server_addr.sin_family = AF_INET;
        server_addr.sin_addr.s_addr = INADDR_ANY;  // 监听所有网络接口
        server_addr.sin_port = htons(port);        // 转换为网络字节序

        if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
            std::cerr << "❌ 绑定地址失败: " << strerror(errno) << std::endl;
            return false;
        }
        std::cout << "✓ 绑定成功，地址: 0.0.0.0:" << port << std::endl;

        // 步骤 5: 开始监听连接
        std::cout << "5. 开始监听连接..." << std::endl;
        if (listen(server_fd, SOMAXCONN) < 0) {
            std::cerr << "❌ 监听失败: " << strerror(errno) << std::endl;
            return false;
        }
        std::cout << "✓ 监听成功，等待客户端连接..." << std::endl;

        // 步骤 6: 创建 epoll 实例
        std::cout << "6. 创建 epoll 实例..." << std::endl;
        epoll_fd = epoll_create1(0);
        if (epoll_fd == -1) {
            std::cerr << "❌ 创建 epoll 实例失败: " << strerror(errno) << std::endl;
            return false;
        }
        std::cout << "✓ epoll 实例创建成功，文件描述符: " << epoll_fd << std::endl;

        // 步骤 7: 将服务器套接字添加到 epoll
        std::cout << "7. 注册服务器套接字到 epoll..." << std::endl;
        if (!addToEpoll(server_fd, EPOLLIN)) {
            std::cerr << "❌ 注册服务器套接字失败" << std::endl;
            return false;
        }
        std::cout << "✓ 服务器套接字注册成功" << std::endl;

        std::cout << "=== 服务器初始化完成 ===" << std::endl;
        return true;
    }

    /**
     * 处理新的客户端连接
     */
    void handleNewConnection() {
        struct sockaddr_in client_addr;
        socklen_t client_len = sizeof(client_addr);
        
        // 接受客户端连接
        int client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &client_len);
        if (client_fd == -1) {
            std::cerr << "[" << getTimestamp() << "] ❌ 接受连接失败: " << strerror(errno) << std::endl;
            return;
        }

        // 检查连接数限制
        if (client_count.load() >= MAX_CLIENTS) {
            std::cout << "[" << getTimestamp() << "] ⚠️  连接数已达上限，拒绝新连接" << std::endl;
            close(client_fd);
            return;
        }

        // 设置客户端套接字为非阻塞
        if (!setNonBlocking(client_fd)) {
            std::cerr << "[" << getTimestamp() << "] ❌ 设置客户端非阻塞失败" << std::endl;
            close(client_fd);
            return;
        }

        // 添加到 epoll - 使用水平触发模式
        if (!addToEpoll(client_fd, EPOLLIN)) {
            std::cerr << "[" << getTimestamp() << "] ❌ 添加客户端到 epoll 失败" << std::endl;
            close(client_fd);
            return;
        }

        // 更新连接统计和客户端信息
        client_count++;
        std::string client_addr_str = std::string(inet_ntoa(client_addr.sin_addr)) + ":" + 
                                     std::to_string(ntohs(client_addr.sin_port));
        
        {
            std::lock_guard<std::mutex> lock(client_mutex);
            client_info[client_fd] = client_addr_str;
        }
        
        std::cout << "[" << getTimestamp() << "] 🎉 新客户端连接成功!" << std::endl;
        std::cout << "   客户端地址: " << client_addr_str << std::endl;
        std::cout << "   客户端文件描述符: " << client_fd << std::endl;
        std::cout << "   当前连接数: " << client_count.load() << "/" << MAX_CLIENTS << std::endl;
    }

    /**
     * 处理客户端数据 - 被动清理版本
     * 
     * 修改策略：
     * 1. 只在客户端真正断开时才清理
     * 2. 改进数据读取逻辑
     * 3. 不主动清理连接
     */
    void handleClientData(int client_fd) {
        char buffer[BUFFER_SIZE];
        ssize_t bytes_read;
        
        std::cout << "[" << getTimestamp() << "] 📥 开始处理客户端 " << client_fd << " 的数据" << std::endl;
        
        // 读取数据（水平触发模式，只需要读取一次）
        bytes_read = recv(client_fd, buffer, BUFFER_SIZE - 1, 0);
        
        if (bytes_read > 0) {
            buffer[bytes_read] = '\0';
            std::cout << "[" << getTimestamp() << "] 📨 收到数据 (客户端 " << client_fd << "): " << buffer;
            
            // 发送回显消息
            std::string response = "服务器回显 [" + getTimestamp() + "]: " + std::string(buffer);
            ssize_t bytes_sent = send(client_fd, response.c_str(), response.length(), 0);
            
            if (bytes_sent > 0) {
                std::cout << "[" << getTimestamp() << "] 📤 发送回显成功 (" << bytes_sent << " 字节)" << std::endl;
            } else if (bytes_sent == -1) {
                std::cerr << "[" << getTimestamp() << "] ❌ 发送回显失败: " << strerror(errno) << std::endl;
            }
        } else if (bytes_read == 0) {
            // 客户端主动断开连接 - 这是唯一清理连接的情况
            std::cout << "[" << getTimestamp() << "] 👋 客户端 " << client_fd << " 主动断开连接" << std::endl;
            cleanupClient(client_fd);
        } else if (bytes_read == -1) {
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
                // 非阻塞模式下，没有更多数据可读 - 不清理连接
                std::cout << "[" << getTimestamp() << "] ✓ 数据读取完成，保持连接" << std::endl;
            } else {
                // 发生错误 - 但仍然不主动清理，等待客户端自己断开
                std::cerr << "[" << getTimestamp() << "] ⚠️  读取客户端 " << client_fd << " 数据时发生错误: " << strerror(errno) << std::endl;
                std::cout << "[" << getTimestamp() << "] ℹ️  保持连接，等待客户端主动断开" << std::endl;
            }
        }
    }

    /**
     * 清理客户端连接 - 只在客户端主动断开时调用
     * @param client_fd 客户端文件描述符
     */
    void cleanupClient(int client_fd) {
        std::cout << "[" << getTimestamp() << "] 🧹 清理客户端 " << client_fd << " 的连接" << std::endl;
        
        // 从 epoll 中移除
        removeFromEpoll(client_fd);
        
        // 关闭套接字
        close(client_fd);
        
        // 更新连接统计和客户端信息
        client_count--;
        {
            std::lock_guard<std::mutex> lock(client_mutex);
            client_info.erase(client_fd);
        }
        
        std::cout << "[" << getTimestamp() << "] ✓ 客户端 " << client_fd << " 清理完成" << std::endl;
        std::cout << "   当前连接数: " << client_count.load() << "/" << MAX_CLIENTS << std::endl;
    }

    /**
     * 统计信息线程
     * 定期输出服务器运行状态
     */
    void statsThread() {
        while (running) {
            std::this_thread::sleep_for(std::chrono::seconds(30));  // 每30秒输出一次统计
            if (running) {
                std::cout << "\n[" << getTimestamp() << "] 📊 服务器运行状态:" << std::endl;
                std::cout << "   当前连接数: " << client_count.load() << "/" << MAX_CLIENTS << std::endl;
                std::cout << "   服务器运行时间: 持续运行中..." << std::endl;
                std::cout << "   内存使用: 正常" << std::endl;
                std::cout << "   清理策略: 被动清理" << std::endl;
                std::cout << "   =================================" << std::endl;
            }
        }
    }

    /**
     * 运行服务器主循环
     */
    void run() {
        struct epoll_event events[MAX_EVENTS];
        running = true;
        
        std::cout << "\n=== 服务器启动，开始事件循环 ===" << std::endl;
        std::cout << "服务器地址: 0.0.0.0:" << port << std::endl;
        std::cout << "最大并发连接: " << MAX_CLIENTS << std::endl;
        std::cout << "事件驱动模型: epoll (水平触发)" << std::endl;
        std::cout << "I/O 模式: 非阻塞" << std::endl;
        std::cout << "连接清理: 被动清理（等待客户端主动断开）" << std::endl;
        std::cout << "=========================================" << std::endl;
        
        // 启动统计线程
        std::thread stats_thread(&PassiveEpollServer::statsThread, this);
        
        // 主事件循环
        while (running) {
            // 等待事件发生（阻塞调用）
            int num_events = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
            
            if (num_events == -1) {
                if (errno == EINTR) {
                    // 被信号中断，继续循环
                    continue;
                }
                std::cerr << "[" << getTimestamp() << "] ❌ epoll_wait 失败: " << strerror(errno) << std::endl;
                break;
            }

            // 处理所有就绪的事件
            for (int i = 0; i < num_events; ++i) {
                if (events[i].data.fd == server_fd) {
                    // 服务器套接字事件 - 新连接
                    std::cout << "[" << getTimestamp() << "] 🔗 检测到新连接请求" << std::endl;
                    handleNewConnection();
                } else {
                    // 客户端套接字事件
                    if (events[i].events & EPOLLIN) {
                        // 可读事件
                        handleClientData(events[i].data.fd);
                    }
                    
                    if (events[i].events & EPOLLERR) {
                        // 错误事件 - 但仍然不主动清理
                        std::cerr << "[" << getTimestamp() << "] ⚠️  客户端 " << events[i].data.fd << " 发生错误，但保持连接" << std::endl;
                    }
                    
                    if (events[i].events & EPOLLHUP) {
                        // 挂起事件（连接断开）- 这是客户端主动断开的情况
                        std::cout << "[" << getTimestamp() << "] 🔌 客户端 " << events[i].data.fd << " 连接挂起（主动断开）" << std::endl;
                        cleanupClient(events[i].data.fd);
                    }
                }
            }
        }
        
        // 等待统计线程结束
        if (stats_thread.joinable()) {
            stats_thread.join();
        }
        
        std::cout << "\n=== 服务器主循环结束 ===" << std::endl;
    }

    /**
     * 优雅关闭服务器
     */
    void shutdown() {
        std::cout << "\n[" << getTimestamp() << "] 🛑 收到关闭信号，开始优雅关闭..." << std::endl;
        running = false;
    }
};

/**
 * 主函数
 */
int main(int argc, char* argv[]) {
    std::cout << "🚀 被动清理版 Epoll 服务器启动" << std::endl;
    std::cout << "版本: 2.2 (被动清理版)" << std::endl;
    std::cout << "作者: AI Assistant" << std::endl;
    std::cout << "功能: 高性能多线程网络通信服务器" << std::endl;
    std::cout << "策略: 被动清理连接，等待客户端主动断开" << std::endl;
    
    // 解析命令行参数
    int port = 8888;
    if (argc > 1) {
        port = atoi(argv[1]);
        if (port <= 0 || port > 65535) {
            std::cerr << "❌ 无效的端口号: " << argv[1] << std::endl;
            std::cerr << "端口号必须在 1-65535 范围内" << std::endl;
            return 1;
        }
    }

    std::cout << "\n📋 启动参数:" << std::endl;
    std::cout << "监听端口: " << port << std::endl;
    std::cout << "使用方法: " << argv[0] << " [端口号]" << std::endl;
    std::cout << "示例: " << argv[0] << " 9999" << std::endl;

    // 创建服务器实例
    PassiveEpollServer server(port);
    
    // 初始化服务器
    if (!server.init()) {
        std::cerr << "\n❌ 服务器初始化失败，程序退出" << std::endl;
        return 1;
    }

    // 运行服务器
    try {
        server.run();
    } catch (const std::exception& e) {
        std::cerr << "\n❌ 服务器运行时发生异常: " << e.what() << std::endl;
        return 1;
    } catch (...) {
        std::cerr << "\n❌ 服务器运行时发生未知异常" << std::endl;
        return 1;
    }
    
    std::cout << "\n✅ 服务器正常退出" << std::endl;
    return 0;
}